﻿using ArtMath.Component;
using ArtMath.Converter;
using ArtMath.Core.Data;
using ArtMath.Core.Helper;
using ArtMath.Resource;
using System;
using System.ComponentModel;
using System.Reflection;
using ArtMath.Component.Point;

namespace ArtMath.Parameter
{
    /// <summary>
    /// 图形参数
    /// </summary>
    [Serializable]
    public class ObjectParameter : ReadOnlyParameter
    {
        Base obj;
        PropertyInfo prop;
        int pos;
        public ObjectParameter(Document doc, string name, Base obj, string paramName, int pos = 0) : base(doc, name, "0")
        {
            this.pos = pos;
            prop = obj.GetType().GetProperty(paramName);
            TypeConverterAttribute[] tca = obj.GetType().GetAttributes<TypeConverterAttribute>(paramName);
            if (tca?.Length > 0)
            {
                foreach (TypeConverterAttribute item in tca)
                {
                    if (item.ConverterTypeName.Contains(nameof(IntelliAngleConverter)))
                    {
                        Unit = ParameterUnit.Radian;
                    }
                }
            }
            Object = obj;
        }
        [Browsable(false)]
        public Base Object
        {
            get { return obj; }
            set
            {
                if (obj is object)
                {
                    obj.ObjectParameters.Remove(this);
                }
                obj = value;
                if (obj is object)
                {
                    obj.ObjectParameters.Add(this);
                    Value.SetExpression(GetNewValue());
                }
            }
        }
        public double GetNewValue()
        {
            object res = prop.GetValue(Object, null);
            if (res is PointD)
            {
                PointD pt = Object.Pad.ShowPoint((PointD)res);
                switch (pos)
                {
                    case 0:
                        return pt.X;
                    case 1:
                        return pt.Y;
                }
            }
            else
            {
                StringX sx = res as StringX;
                if (sx is object)
                {
                    return sx.Value;
                }
            }
            return (double)res;
        }
        protected override void ForEachRelatedObject(Predicate<Base> action)
        {
            if (action == null) return;
            if (!action(Object)) return;
        }
        public override void Delete(bool recoverable = false)
        {
            base.Delete(recoverable);
            if (recoverable)
            {

            }
            else
            {
                Object = null;
            }
        }
        public override void ChangePoint(PointBase oldPoint, PointBase newPoint)
        {
            if (ReferenceEquals(Object, oldPoint))
            {
                Object = newPoint;
            }
            else
            {
                base.ChangePoint(oldPoint, newPoint);
            }
        }
    }
}
